Skip to content

fix(web): focus the primary action when confirmation dialogs open - #18187

Open
rgrvlsk wants to merge 7 commits into
pingdotgg:mainfrom
rgrvlsk:fix/dialog-initial-focus
Open

rgrvlsk wants to merge 7 commits into
pingdotgg:mainfrom
rgrvlsk:fix/dialog-initial-focus

Conversation

@rgrvlsk

@rgrvlsk rgrvlsk commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Selected update and install confirmation dialogs focus Cancel even though the primary action is visually emphasized. Pressing Enter therefore cancels. This change lets those prompts opt into primary-action focus while keeping generic and destructive confirmations Cancel-first.

A shared DialogAction marker selects the enabled primary button on popup open. Explicit caller focus wins, caller refs remain composed, and touch opening retains popup focus. Desktop update prompts in Settings, current and legacy sidebars, and remote single/batch update actions opt in. Relay install and browser-import quit/retry screens use the same marker. The broad Update everything dialog keeps its existing behavior.

Based on @rgrvlsk’s original contribution. Contributor history is preserved; main was merged and the implementation rebuilt against current primitives. The rebuild fixes caller refs overriding the internal focus ref and removes redundant comments and runtime variant bookkeeping.

Verification for rebuilt head 0c37cce149:

  • Focused suites: 35 passed in 3 files, versus 35 in 4 files before test cleanup. Seven jsdom cases with fixed sleeps were replaced with six Chromium interaction cases; existing remote-update tests exercise the real host with Enter/Space, and the existing coordinator suite covers queued preferences. Restoring main’s host produces two expected focus failures; restoring the original hook produces a caller-ref regression failure.
  • Web, contracts, desktop, and mobile typechecks passed. Scoped lint and formatting passed. An independent reviewer also ran the local API suite: 43 passed in 4 files.
  • One full-diff review round, Claude Opus 5.5 and Codex GPT-6 Sol: no substantive findings. Both rechecked the earlier concern about MCP approvals, checkpoint rollback, and sign-out becoming Enter-to-approve; those callers retain Cancel focus.
  • Live headless Chromium, isolated dev state: opted-in update Confirm receives focus, Enter and Space confirm, Tab reaches Cancel; generic and destructive confirmations focus Cancel and Enter cancels, including destructive plus explicit confirm opt-in. The real relay prompt focuses Download and install and resolves on Enter. The actual BrowserImportWizard, mounted with synthetic callbacks, focuses and activates its initial quit/retry actions.
  • Browser-import later steps retain the persistent popup: after asynchronous retry failure, focus returns to the popup. This change only chooses focus when opening and does not claim automatic refocusing between wizard steps.

The screenshots use the same synthetic app data, 1280×800 viewport, dialog text, and Liberation Sans fallback font. Baseline web focus code matches main ab6be13d43; head is 0c37cce149. The live coordinator was invoked with the real update message/options; no real updates, relay installation, cookie import, or tool approval ran.

Before: Cancel focused After: Confirm focused
Before: update confirmation focuses Cancel After: update confirmation focuses Confirm

Head recording: Enter confirms the opted-in update, cancels generic approval, and cancels destructive confirmation

Not verified: packaged Electron desktop, actual update execution from Settings/sidebar or remote batch, macOS, Windows, physical touch/soft keyboards, screen readers, iOS, or Android. Mobile uses its separate native dialogs. Synthetic Chromium touch tests verify popup focus; they do not verify OS keyboard behavior.

Implementation: Codex GPT-6.1 Sol; tests: Codex GPT-6 Astra; reviews: Claude Opus 5.5 and Codex GPT-6 Sol. Harness: T3 Code through Codex.

Dialogs focused Cancel on open, so pressing Enter cancelled even though
Confirm is the highlighted action. Popups now focus the AlertDialogAction
or DialogAction when they open, so Enter and Space confirm and Tab reaches
Cancel, with native button semantics. Destructive actions aren't marked,
so those dialogs keep focus on Cancel. Touch opens still focus the popup.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Oct 11, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs Human Approval

Macroscope's review found this PR requires human approval — This PR changes keyboard focus and Enter/Space activation in existing update, installation, retry, and import dialogs, including workflows that trigger substantial actions. The shared dialog primitives and several production call sites are changed, so the product-default interaction changes warrant review.

You can add or adjust custom eligibility rules. Learn more.

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Oct 11, 2026
@juliusmarminge juliusmarminge added the macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews label Oct 11, 2026 — with ChatGPT Codex Connector
@macroscopeapp
macroscopeapp Bot dismissed their stale review October 11, 2026 10:45

Dismissing prior approval to re-evaluate 894463f

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Oct 11, 2026
@coderabbitai

coderabbitai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Warning

Review limit reached

Only developers with an assigned seat can use this organization's usage-based review budget, and seats here are assigned manually. Ask an admin to assign a seat, or change the review continuation mode in Billing.

Next included review available in 3 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Path: .coderabbit.config.ts
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: be0a5e6b-758e-4896-b37d-a464e58d2587
📥 Commits

Reviewing files that changed from the base of the PR and between 6f46e56 and 201a29e.

📒 Files selected for processing: 14
  • apps/web/src/components/ConfirmDialogHost.tsx
  • apps/web/src/components/LegacySidebar.tsx
  • apps/web/src/components/ServerUpdateAction.browser.test.tsx
  • apps/web/src/components/ServerUpdateAction.tsx
  • apps/web/src/components/cloud/RelayClientInstallDialog.tsx
  • apps/web/src/components/settings/BrowserImportWizard.tsx
  • apps/web/src/components/settings/SettingsPanels.tsx
  • apps/web/src/components/sidebar/SidebarUpdatePill.tsx
  • apps/web/src/components/ui/alert-dialog.tsx
  • apps/web/src/components/ui/dialog.browser.test.tsx
  • apps/web/src/components/ui/dialog.tsx
  • apps/web/src/confirmDialog.test.ts
  • apps/web/src/confirmDialog.ts
  • packages/contracts/src/ipc.ts

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Path: .coderabbit.config.ts
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: eb2d1a97-60ea-4138-a22a-52ba5f8342c0
📥 Commits

Reviewing files that changed from the base of the PR and between 894463f and 6f46e56.

📒 Files selected for processing (10)
  • apps/web/src/components/ConfirmDialogHost.test.tsx
  • apps/web/src/components/ConfirmDialogHost.tsx
  • apps/web/src/components/LegacySidebar.tsx
  • apps/web/src/components/ServerUpdateAction.tsx
  • apps/web/src/components/settings/SettingsPanels.tsx
  • apps/web/src/components/sidebar/SidebarUpdatePill.tsx
  • apps/web/src/components/ui/dialog.test.tsx
  • apps/web/src/components/ui/dialog.tsx
  • apps/web/src/confirmDialog.ts
  • packages/contracts/src/ipc.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.

📝 Walkthrough

Dialog components now support initial-focus options for confirmation dialogs. They focus eligible actions when a dialog opens. Several confirmation callers request focus on Confirm.

Changes: Dialog Initial Focus

Layer / File(s) Summary
Carry confirmation focus options
packages/contracts/src/ipc.ts, apps/web/src/confirmDialog.ts
ConfirmDialogOptions adds "confirm" and "cancel" focus choices. Active, queued, and closing confirmation states preserve the selected option.
Select dialog initial focus
apps/web/src/components/ui/dialog.tsx, apps/web/src/components/ui/alert-dialog.tsx, apps/web/src/components/ui/dialog.test.tsx
Dialog popups select an enabled marked action for initial focus, or the popup on touch opens. Alert dialogs connect the focus hook and export AlertDialogAction. Tests cover default, disabled, and caller-provided focus targets.
Apply focus-aware confirmation actions
apps/web/src/components/ConfirmDialogHost.tsx, apps/web/src/components/ConfirmDialogHost.test.tsx, apps/web/src/components/LegacySidebar.tsx, apps/web/src/components/ServerUpdateAction.tsx, apps/web/src/components/settings/SettingsPanels.tsx, apps/web/src/components/sidebar/SidebarUpdatePill.tsx, apps/web/src/components/cloud/RelayClientInstallDialog.tsx, apps/web/src/components/settings/BrowserImportWizard.tsx
Update confirmation callers request focus on Confirm. ConfirmDialogHost uses AlertDialogAction for eligible confirmations. Relay install and browser import actions use DialogAction. Tests cover default, requested, and destructive confirmation focus.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Low

Sequence Diagram(s)

sequenceDiagram
  participant ConfirmCaller
  participant ConfirmDialogState
  participant ConfirmDialogHost
  participant DialogPopup
  ConfirmCaller->>ConfirmDialogState: Set initialFocus option
  ConfirmDialogState->>ConfirmDialogHost: Publish confirmation state
  ConfirmDialogHost->>DialogPopup: Render focus-aware action
  DialogPopup->>DialogPopup: Focus eligible action on open
Loading

Suggested reviewers: juliusmarminge

Merge Risk: ⚪ Minimal · up to 6f46e

This change focuses Confirm when update-confirmation dialogs open, and other confirmations keep Cancel focused by default. No concrete merge-blocking issue was found, and the worst case is a minor focus inconsistency.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 6f46e

The change selects an initial focus target rather than granting new permissions or removing confirmation. Ordinary and destructive confirmations retain Cancel unless an eligible action explicitly opts in. No security bypass was established in the inspected flows, but external-caller and runtime coverage remains incomplete.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The most consequential inspected focus change reaches confirmations for selected remote desktop machines, including a batch-update path. Their existing target selection and confirmation remain in place; the PR changes the keyboard-default choice rather than introducing additional execution targets. Broader tenant or deployment exposure was not established.

Trust Boundaries and Controls

  • observed — The inspected MCP approval bridge passes only a message to requestConfirmDialog, not focus options. ConfirmDialogHost renders message-derived content as text and marks Confirm only when the state explicitly requests it and the variant is default. This path therefore retains its previous Cancel-first approval behavior.
  • observed — Shared action selection excludes natively disabled elements. Destructive-action exclusion in DialogAction is a compile-time contract, whereas ConfirmDialogHost also enforces a runtime default-variant condition. These are focus-selection safeguards, not substitutes for operation authorization.

Resilience and Maintainability Implications

  • observed — The confirmation transition assessment found focus metadata preserved across active, closing, and queued states without changing response ownership or cleanup. The inspected relay confirmation handler requires a confirming state and a live resolver, clears that resolver before resolution, and rejects overlapping installation requests.
Pre-merge checks: Passed 3 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Description check Warning The description thoroughly explains the problem, implementation, verification, screenshots, recording, limitations, and agent details. However, it does not provide the required Scope and approval info… Add a Scope and approval section. Link the triaged issue or maintainer discussion, include explicit approval of the direction and scope, or explain why this focused fix qualifies for an approval exemption.
Passed Passed checks: 3 passed
Check name Status Explanation
Linked Issues check Passed Issue [#18167] now defines targeted scope for desktop and server update prompts, relay client install, and browser import "quit" and "try again" steps. The PR applies initialFocus to those call site…
Out of Scope Changes check Passed The dialog focus hook, DialogAction, ConfirmDialogHost option, contract plumbing, targeted call-site changes, and tests support [#18167]. The default Cancel focus for shared confirmations and dest…
Title check Passed The title clearly and concisely describes the primary change: focusing the primary action when confirmation dialogs open.
Full details: Linked Issues check

Explanation

Issue [#18167] now defines targeted scope for desktop and server update prompts, relay client install, and browser import "quit" and "try again" steps. The PR applies initialFocus to those call sites and implements DialogAction in the Dialog and AlertDialog primitives. The shared host remains Cancel-first by default and supports explicit confirm focus. Destructive confirms remain Cancel-first. Reported tests cover primary focus, disabled Confirm, caller overrides, host defaults, opt-in focus, and destructive opt-in behavior.

Full details: Out of Scope Changes check

Explanation

The dialog focus hook, DialogAction, ConfirmDialogHost option, contract plumbing, targeted call-site changes, and tests support [#18167]. The default Cancel focus for shared confirmations and destructive confirmations is an intentional safety behavior within the issue scope. No unrelated change is demonstrated.

Full details: Description check

Explanation

The description thoroughly explains the problem, implementation, verification, screenshots, recording, limitations, and agent details. However, it does not provide the required Scope and approval information, such as a triaged issue or explicit maintainer approval of the direction and scope.

Resolution

Add a Scope and approval section. Link the triaged issue or maintainer discussion, include explicit approval of the direction and scope, or explain why this focused fix qualifies for an approval exemption.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

ConfirmDialogHost serves every requestConfirmDialog and dialogs.confirm
caller, so focusing Confirm there also made Enter approve MCP tool
requests, roll back checkpoints and sign out providers. The host now
keeps Cancel focused unless the caller passes initialFocus: "confirm",
and only the desktop and server update prompts do.

DialogAction now rejects destructive Button variants at compile time
instead of matching the variant name, which missed ghost-destructive.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@macroscopeapp
macroscopeapp Bot dismissed their stale review October 11, 2026 11:15

Dismissing prior approval to re-evaluate 6f46e56

@rgrvlsk

rgrvlsk commented Oct 11, 2026

Copy link
Copy Markdown
Contributor Author

Re CodeRabbit's security note: good catch. ConfirmDialogHost serves every requestConfirmDialog / dialogs.confirm caller, and MCP tool approvals, checkpoint rollback and provider sign-out all use the default variant, so they would have become Enter-to-confirm too. Fixed in 6f46e56: the host now keeps Cancel focused unless the caller passes initialFocus: "confirm", and only the update prompts opt in. Focus preference is now separate from destructive styling, and DialogAction rejects destructive Button variants at compile time. Added host tests for the default, the opt-in, and destructive + opt-in.

@rgrvlsk

rgrvlsk commented Oct 11, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai run pre-merge checks

@coderabbitai

coderabbitai Bot commented Oct 11, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Running Pre-merge checks. Results will be posted in the summary comment once complete.

@juliusmarminge juliusmarminge self-assigned this Oct 19, 2026
@juliusmarminge

Copy link
Copy Markdown
Member

Taking over this one. I’ll rebuild on current main, trim the tests to meaningful focus behavior, and push to this branch while keeping generic and destructive confirmations Cancel-first.

@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Oct 19, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants